package de.islanders.unit.player;

import java.util.concurrent.CountDownLatch;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.OneToOne;

import de.islanders.exceptions.NoToolException;
import de.islanders.gameobject.Food;
import de.islanders.gameobject.Material;
import de.islanders.interfaces.Collectable;
import de.islanders.interfaces.Edible;
import de.islanders.interfaces.Equipable;
import de.islanders.interfaces.Harvestable;
import de.islanders.interfaces.Mineable;
import de.islanders.interfaces.Placeable;
import de.islanders.interfaces.Scavengeable;
import de.islanders.shared.CastBar;
import de.islanders.unit.Gender;
import de.islanders.unit.Unit;
import de.islanders.world.Position;

@Entity
@Inheritance // FIXME inheritance
public class Player extends Unit {

	@OneToOne() //FIXME relation
	private PlayerStatus status;
	@OneToOne() //FIXME relation
	private Inventory inventory;
	@OneToOne() // FIXME relation
	private Equip equip;
	@Column
	private int size;
	@Column
	private double weight;
	@Column
	private Gender gender;
	@OneToOne() //FIXME relation
	private Skills skills;

	public Player(String name, double scale, Position position, int size, double weight) {
		super(name, scale, position);
		this.status = new PlayerStatus(inventory);
		this.size = size;
		this.weight = weight;
	}
	
	/**
	 * @return the status
	 */
	public PlayerStatus getStatus() {
		return status;
	}

	/**
	 * @param status the status to set
	 */
	public void setStatus(PlayerStatus status) {
		this.status = status;
	}

	/**
	 * @return the inventory
	 */
	public Inventory getInventory() {
		return inventory;
	}

	/**
	 * @param inventory
	 *            the inventory to set
	 */
	public void setInventory(Inventory inventory) {
		this.inventory = inventory;
	}

	/**
	 * @return the size
	 */
	public int getSize() {
		return size;
	}

	/**
	 * @param size
	 *            the size to set
	 */
	public void setSize(int size) {
		this.size = size;
	}

	/**
	 * @return the weight
	 */
	public double getWeight() {
		return weight;
	}

	/**
	 * @param weight
	 *            the weight to set
	 */
	public void setWeight(double weight) {
		this.weight = weight;
	}

	/**
	 * @return the equip
	 */
	public Equip getEquip() {
		return equip;
	}

	/**
	 * @param equip the equip to set
	 */
	public void setEquip(Equip equip) {
		this.equip = equip;
	}

	/**
	 * @return the gender
	 */
	public Gender getGender() {
		return gender;
	}

	/**
	 * @param gender the gender to set
	 */
	public void setGender(Gender gender) {
		this.gender = gender;
	}
	
	/**
	 * @return the skills
	 */
	public Skills getSkills() {
		return skills;
	}

	/**
	 * @param skills the skills to set
	 */
	public void setSkills(Skills skills) {
		this.skills = skills;
	}

	public void collect(Collectable item) {
		if(item instanceof Food){
			inventory.add((Food) item);
		} else if(item instanceof Material){
			inventory.add((Material) item);
		}
	}

	public void harvest(Harvestable item) throws NoToolException {
		if(item instanceof Food){
			inventory.add((Food) item);
		}
	}

	public void eat(Edible item) {
		Food food = (Food) item;
		status.setHunger(status.getHunger() - food.getHungerReduction());
	}

	// FIXME replace null with item
	public void mine(Mineable item) throws NoToolException {
		if (equip.getEquipSlot(Equip.SLOT_HAND_R) != null) {
			if(item instanceof Material){
				CountDownLatch threadMonitor = new CountDownLatch(1);
				Thread castbar = new Thread(new CastBar(8, threadMonitor));
				castbar.start();
				try {
					threadMonitor.await();
					inventory.add((Material)item);
				} catch (InterruptedException e) {}	
			}
		} else {
			throw new NoToolException("You can't mine that without a proper tool.");
		}
	}

	public void place(Placeable item, Position targetLocation) {

	}

	public void scavenge(Scavengeable building) {
		
	}

	public void equip(Equipable item) {

	}
}